package zm.irc.ioc.classCollector;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;

import zm.irc.ioc.pojo.WrapClass;

public class ClassCollector {
    private static final Logger log = Logger.getLogger(ClassCollector.class);    

    public static final ClassCollector CLASS_COLLECTOR;
    private static final List<ClassEnrichment> enrichmentChain;
    
    static {
        synchronized(ClassCollector.class){
            enrichmentChain = new ArrayList<>();
            enrichmentChain.add(new BeanClassFilter());
            enrichmentChain.add(new AutoWiredFieldEnrichment());
            enrichmentChain.add(new ConfigurationEnrichment());
            CLASS_COLLECTOR = new ClassCollector();
        }
    }



    private ClassCollector(){}

    /**
     * Collecte all classes recursively.
     * @param path
     * @return
     */
    public Set<WrapClass> collecte(String path){
        log.debug("Load class start.(Path is " + path + ")");
        Set<WrapClass> clazzes = new HashSet<>();
        this.doCollecte(clazzes, path, "");

        /* The return value of previous should be the input value of the next. */
        for(ClassEnrichment enrichment : enrichmentChain){
            clazzes = enrichment.enrich(clazzes);
        }
        WrapClass.initChildMap();
        return clazzes;
    }


    /**
     * Collecte class into clazzes from {path}
     * @param clazzes
     * @param path
     * @param className
     */
    private void doCollecte(Set<WrapClass> clazzes,String path,String classPath){
        File currentFolder = new File(path);
        File[] files = currentFolder.listFiles();
        if(files == null || files.length == 0){
            return;
        }
        for(File file : files){
            String fileName = file.getName();
            if(file.isDirectory()){
                this.doCollecte(clazzes, path+"/" + fileName, classPath  + fileName.replace(".class", "")+".");
            }
            if( isClassFile(file)){
                String className = classPath+ fileName.replace(".class", "");
                Class<?> clazz = this.loadClass(className);
                clazzes.add(WrapClass.build(clazz));
            }
        }
    }
    

    private boolean isClassFile(File file){
        return file!=null && file.isFile() && file.getName().endsWith(".class");
    }

    private Class<?> loadClass(String className){
        try{
            return Class.forName(className);
        }catch(Exception e){
            log.error("Load class error!",e);
        }
        return null;
    }


}
